# -*- coding: UTF-8 -*-
'''
Created on 2012-4-14

@author: Who EastBlue

请先将8个loaddata/0004/p*.bin文件复制到项目的res/文件夹中
'''

import zlib
import Util
import os

def unzipBin(binPath):
    print binPath
    f_bin = open('../res/' + binPath, 'rb')

    # [0008H]: 包含小文件的数量count.
    # File.seek(offset[, whence]),
    # whence(何处)=0(默认)为绝对位置/相对文件开头的位置
    #             =1为相对当前的位置,
    #             =2为相对文件结尾的位置. 
    f_bin.seek(8, 0)
    count = Util.binArray2num("<L", f_bin.read(4))
    print 'include %s files:' % (count)

    # 从[000CH]开始,是 count对双字参数
    # 每对参数分别是:每个小文件的绝对起始地址,和小文件的长度.
    # 前一个起始地址+小文件长度=后一个起始地址
    splitStartAddress = [[]] * count
#    splitLen = [[]] * count
    for i in range(count):
        splitStartAddress[i] = Util.binArray2num("<L", f_bin.read(4))
#        splitLen[i] = Util.binArray2num("<L", f_bin.read(4))
        f_bin.seek(4, 1)

    # 处理每个小文件的数据
    for i_file in range(count):
        # 跳到小文件数据的开头,
        # 每一个小文件数据正文之后,都以4个字节的0x00结尾,
        # 已读的压缩后数据长度,加上这个后缀,才等于大文件头中的小文件长度的值
        f_bin.seek(splitStartAddress[i], 0)

        # 每段小文件的数据结构:
        # [4 Bytes] [ [4 Bytes, value=len][len Bytes] ][ [4 Bytes, value=len][len Bytes] ]...
        # 首4字节的值为解压后的文件大小,
        # 之后是N段分卷压缩后的数据,每小段包括两部分:
        # 首4字节的值为此小段压缩后数据的长度len,
        # 然后是len字节的压缩后数据.
        
        # 解压后文件的大小
        unzipFileSize = Util.binArray2num("<L", f_bin.read(4))
        
        unzipFileName = '../export/%s_%s' % (binPath[0:-4], i_file)
        f = open(unzipFileName, 'wb')
        print '  ' + unzipFileName
        
        # 解压后的文件,即压缩前的原文件,是先切成N个32768字节的小块,分别进行压缩,再连接到一起的.
        # 算出有多少小块,就是每个小文件有几段压缩后数据.
        blockSize = 32768
        blockCount = (unzipFileSize - 1) / blockSize + 1
        while blockCount > 0:
            # 此块压缩后数据的长度
            zipDataSize = Util.binArray2num("<L", f_bin.read(4))
            zipData = f_bin.read(zipDataSize)
            # 用zlib库提供的函数解压
            unzipData = zlib.decompress(zipData)
            f.write(unzipData)
            blockCount -= 1
        if not (f.tell() == unzipFileSize):
            print '#### %s len is error.' % (unzipFileName)
        f.close()
        i_file += 1
    f_bin.close()

if __name__ == '__main__':
    if not os.path.exists('../export'):
        os.mkdir('../export')
    # 可注释掉不想解压的文件
    files = [\
'p00026000.bin', \
'p00027000.bin', \
'p00027010.bin', \
'p00027020.bin', \
'p00027030.bin', \
'p00027040.bin', \
'p00027050.bin', \
'p00028000.bin', \
]
    for file in files:
        unzipBin(file)
